package metaphor.service;

import org.springframework.security.acls.Permission;
import org.springframework.security.acls.sid.Sid;

/**
 * @author Mark Ashworth <javameme@gmail.com>
 * @version 1.0.0
 * @since 1.0.0
 */
public interface SecurityManager {
    /**
     * Grants read permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantRead(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Grants write permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantWrite(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Grants create permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantCreate(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Grants delete permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantDelete(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Grants administration permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantAdministration(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Grants all permissions to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantAll(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;
    
    /**
     * Grants a permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @param permission The permission to grant to the user
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantPermission(
            Class persistentClass,
            Long id,
            Sid sid,
            Permission permission) throws metaphor.service.SecurityException;

    /**
     * Grants a set of permissions to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity of whom to grant access to
     * @param permissions The permissions to grant to the user
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void grantPermission(
            Class persistentClass,
            Long id,
            Sid sid,
            Permission[] permissions) throws metaphor.service.SecurityException;
    
    /**
     * Grants a permission to the user on the object defined by the persistentClass
     * and object identifier.<br />
     *
     * @param persistentClass The class to grant access to
     * @param id The object identifier of the persistent class
     * @param sid The security identity to grant the permission to
     * @param permission The permission to grant to the user
     * @throws metaphor.service.SecurityException If there was an error
     */
    public void denyPermission(
            Class persistentClass,
            Long id,
            Sid sid,
            Permission permission) throws metaphor.service.SecurityException;

    /**
     * Change the owner of a persistent object.<br />
     * @param persistentClass The persistent class
     * @param id The object identifier of the persistent class object
     * @param sid The security identity of the new owner
     * @throws metaphor.service.SecurityException If there was an error
     */

    public void changeOwnership(
            Class persistentClass,
            Long id,
            Sid sid) throws metaphor.service.SecurityException;

    /**
     * Determines authorization.  The order of the <code>permission</code> and <code>sid</code> arguments is
     * <em>extremely important</em>! The method will iterate through each of the <code>permission</code>s in the order
     * specified. For each iteration, all of the <code>sid</code>s will be considered, again in the order they are
     * presented. A search will then be performed for the first {@link org.springframework.security.acls.AccessControlEntry} object that directly
     * matches that <code>permission:sid</code> combination. When the <em>first full match</em> is found (ie an ACE
     * that has the SID currently being searched for and the exact permission bit mask being search for), the grant or
     * deny flag for that ACE will prevail. If the ACE specifies to grant access, the method will return
     * <code>true</code>. If the ACE specifies to deny access, the loop will stop and the next <code>permission</code>
     * iteration will be performed. If each permission indicates to deny access, the first deny ACE found will be
     * considered the reason for the failure (as it was the first match found, and is therefore the one most logically
     * requiring changes - although not always). If absolutely no matching ACE was found at all for any permission,
     * the parent ACL will be tried (provided that there is a parent and {@link org.springframework.security.acls.Acl#isEntriesInheriting()} is
     * <code>true</code>. The parent ACL will also scan its parent and so on. If ultimately no matching ACE is found,
     * a <code>NotFoundException</code> will be thrown and the caller will need to decide how to handle the permission
     * check. Similarly, if any of the SID arguments presented to the method were not loaded by the ACL,
     * <code>UnloadedSidException</code> will be thrown.
     *
     * @param persistentClass The persistent class
     * @param id The object identifier of the persisten class object
     * @param permissions the exact permissions to scan for (order is important)
     * @param sids the exact SIDs to scan for (order is important)
     * @param administrativeMode if <code>true</code> denotes the query is for administrative purposes and no auditing
     *        will be undertaken
     *
     * @return SecurityGranted.GRANTED, DENIED, NOTFOUND
     *
     * @throws org.springframework.security.acls.NotFoundException if an exact ACE for one of the permission bit masks and SID combination could not be
     *         found
     * @throws org.springframework.security.acls.UnloadedSidException if the passed SIDs are unknown to this ACL because the ACL was only loaded for a
     *         subset of SIDs
     *
     * @throws metaphor.service.SecurityException If there was an error checking
     */
    public SecurityGranted isGranted(
            Class persistentClass,
            Long id,
            Permission[] permissions,
            Sid[] sids,
            boolean administrativeMode) throws metaphor.service.SecurityException;

}